/**
 * board_2018 穿梭背景
 */

import Layout from './layout';
import Color from './color';

let zrender;

class Transfer {
  context = null;

  canvasWidth = 0;
  canvasHeight = 0;
  /** @type {Layout} */
  layout = null;
  /** @type {Color} */
  color = null;

  zr = null;

  sprites = {
    // 背景板
    bg : null,
    bgUpdater : null, // 更新时用
    // 扫描线
    bgLines : null,
    // 白色竖线
    bgTiles : [],
    // 白色中心横线
    bgHorizontal : null,
    // 背景动态部分, 横向移动的
    bgMoverRight : [],
    bgMoverLeft : [],
    // 背景动态部分, 纵向移动的
    bgMoverTop : [],
    bgMoverBottom : [],
    
    // 背景挖空的
    screenRm : []
  };

  params = {
    // 计数器
    bgMoverCount : 0,
    // 各个 bg_mover_right 的位置参数
    // 每个部分: {posx : number, opacity : number, count : number, width : number}
    bgMoverRight : [],
    // 各个 bg_mover_left 的位置参数
    // 每个部分: {posx : number, opacity : number, count : number, width : number}
    bgMoverLeft : [],
    // 各个 bg_mover_top 的位置参数
    // 每个部分: {posy : number, count : number, height : number}
    bgMoverTop : [],
    // 各个 bg_mover_bottom 的位置参数
    // 每个部分: {posy : number, count : number, height : number}
    bgMoverBottom : []

  };
  
  handler = {
    /** @type {number} 背景的 mover */
    bgMover : null
  };

  constructor(context) {
    this.context = context;
  }

  // 原有方法
  init(libs, options) {
    zrender = libs.zrender;
    this.zr = zrender.init(document.getElementById(options.dom));

    this.canvasWidth = options.width;
    this.canvasHeight = options.height;
    this.layout = options.layout;
    this.color = options.color;

    this.initBackground();

    // 动态移动部分
    this.handler.bgMover = setInterval(() => this.tick(), 1000 / 60);
  }

  destroy() {
    //
  }

  initBackground() {
    // 创建背景颜色
    this.zr.add(this.sprites.bg =
      createBackground(this.canvasWidth, this.canvasHeight, this.color));
    
    // 其它线条
    this.zr.add(this.sprites.bgLines =
      createScanLine(this.canvasWidth, this.canvasHeight));

    // 中心白竖线
    createBgTiles(this.canvasWidth, this.canvasHeight).forEach(item => {
      this.sprites.bgTiles.push(item);
      this.zr.add(item);
    });

    // 中心白横线
    this.zr.add(this.sprites.bgHorizontal =
      createBgHorizontal(this.canvasWidth, this.layout));
    
    // 两个挖空的方形
    createScreenRemovers(this.layout).forEach(item => {
      this.sprites.screenRm.push(item);
      this.zr.add(item);
    });
  }

  /**
   * 场景向该挂件发送指令的地方
   * 更新 style. style 是 'dark' 或 'light'
   * @param {string} style 
   */
  updateBgStyle(style) {
    if (this.sprites.bgUpdater != null) {
      this.zr.remove(this.sprites.bg);
      this.sprites.bgUpdater.stopAnimation(true);
      this.sprites.bg = this.sprites.bgUpdater;
      this.sprites.bgUpdater = null;
    }

    let toColorBg = this.color[style + "_bg"];

    this.zr.add(this.sprites.bgUpdater = new zrender.Rect({
      shape: {
        width: this.canvasWidth,
        height: this.canvasHeight
      },
      style: {
        fill: new zrender.LinearGradient(
          0, 0, 1, 0,
          [
            {offset:0, color:toColorBg[1]},
            {offset:0.333, color:toColorBg[0]},
            {offset:0.5, color:'white'},
            {offset:0.667, color:toColorBg[0]},
            {offset:1, color:toColorBg[1]}
          ]
        ),
        opacity: 0
      },
      position: [0, 0],
      z: 0
    }));
    this.sprites.bgUpdater.animate('style', false)
      .when(1000, {opacity:1})
      .done(() => {
        this.zr.remove(this.sprites.bg);
        this.sprites.bg = this.sprites.bgUpdater;
        this.sprites.bgUpdater = null;
      })
      .start('cubicInOut');
  }

  tick() {
    if (document.hidden) {return;}

    this.updateBgMover();
  }

  updateBgMover() {
    const ystart = this.layout.bgMoverOriY;

    // 原先的
    // to right
    let rsprites = this.sprites.bgMoverRight; // array
    let rparams = this.params.bgMoverRight; // array
    for (let i = rsprites.length - 1; i >= 0; i--) {
      let rsprite = rsprites[i];
      let rparam = rparams[i];
      rparam.count++;

      // offset + 2x + 0.01x^2
      rparam.posx = this.canvasWidth * 0.25 + 2 * rparam.count + 0.01 * rparam.count * rparam.count;
      rparam.opacity = 0.001 * rparam.count;
      if (rparam.opacity > 0.1) {
        rparam.opacity = 0.1;
      }
      rparam.width = rparam.count / 2.5 + 0.0008 * rparam.count * rparam.count;
      if (rparam.posx > this.canvasWidth) {
        rsprites.splice(i, 1);
        rparams.splice(i, 1);
        this.zr.remove(rsprite);
      } else {
        rsprite.attr({position:[rparam.posx, 0],shape:{width:rparam.width},style:{opacity:rparam.opacity}});
      }
    }

    // to left
    let lsprites = this.sprites.bgMoverLeft; // array
    let lparams = this.params.bgMoverLeft; // array
    for (let i = lsprites.length - 1; i >= 0; i--) {
      let lsprite = lsprites[i];
      let lparam = lparams[i];
      lparam.count++;

      lparam.opacity = 0.001 * lparam.count;
      if (lparam.opacity > 0.1) {
        lparam.opacity = 0.1;
      }
      lparam.width = lparam.count / 2.5 + 0.0008 * lparam.count * lparam.count;
      lparam.posx = this.canvasWidth * 0.75 - 2 * lparam.count - 0.01 * lparam.count * lparam.count - lparam.width;
      if (lparam.posx < -lparam.width) {
        lsprites.splice(i, 1);
        lparams.splice(i, 1);
        this.zr.remove(lsprite);
      } else {
        lsprite.attr({position:[lparam.posx, 0],shape:{width:lparam.width},style:{opacity:lparam.opacity}});
      }
    }

    // to top
    let tsprites = this.sprites.bgMoverTop; // array
    let tparams = this.params.bgMoverTop; // array
    for (let i = tsprites.length - 1; i >= 0; i--) {
      let tsprite = tsprites[i];
      let tparam = tparams[i];
      tparam.count++;

      tparam.height = 0.004 * tparam.count * tparam.count;
      tparam.posy = ystart - 0.005 * tparam.count * tparam.count - tparam.height;
      if (tparam.posy < -tparam.height) {
        tsprites.splice(i, 1);
        tparams.splice(i, 1);
        this.zr.remove(tsprite);
      } else {
        tsprite.attr({position:[0, tparam.posy],shape:{height:tparam.height}});
      }
    }

    // to bottom
    let bsprites = this.sprites.bgMoverBottom; // array
    let bparams = this.params.bgMoverBottom; // array
    for (let i = bsprites.length - 1; i >= 0; i--) {
      let bsprite = bsprites[i];
      let bparam = bparams[i];
      bparam.count++;

      bparam.height = 0.004 * bparam.count * bparam.count;
      bparam.posy = ystart + 0.005 * bparam.count * bparam.count;
      if (bparam.posy > this.canvasHeight) {
        bsprites.splice(i, 1);
        bparams.splice(i, 1);
        this.zr.remove(bsprite);
      } else {
        bsprite.attr({position:[0, bparam.posy],shape:{height:bparam.height}});
      }
    }

    // 新添加的
    if (this.params.bgMoverCount % 85 == 0) {
      // to right
      let rparam = {
        count: 0,
        posx: this.canvasWidth * 0.25,
        opacity: 0.001,
        width: 1
      };
      let rsprite = new zrender.Rect({
        shape: {
          width: rparam.width,
          height: this.canvasHeight
        },
        style: {
          fill: new zrender.LinearGradient(
            0, 0, 1, 0,
            [
              {offset:0, color:'#FFF0'},
              {offset:0.2, color:'#FFF'},
              {offset:0.8, color:'#FFF'},
              {offset:1, color:'#FFF0'}
            ]
          ),
          opacity: rparam.opacity
        },
        position: [rparam.posx, 0],
        z: 1
      });
      this.zr.add(rsprite);
      rsprites.push(rsprite);
      rparams.push(rparam);

      // to left
      let lparam = {
        count: 0,
        posx: this.canvasWidth * 0.75 - 1,
        opacity: 0.001,
        width: 1
      };
      let lsprite = new zrender.Rect({
        shape: {
          width: lparam.width,
          height: this.canvasHeight
        },
        style: {
          fill: new zrender.LinearGradient(
            0, 0, 1, 0,
            [
              {offset:0, color:'#FFF0'},
              {offset:0.2, color:'#FFF'},
              {offset:0.8, color:'#FFF'},
              {offset:1, color:'#FFF0'}
            ]
          ),
          opacity: lparam.opacity
        },
        position: [lparam.posx, 0],
        z: 1
      });
      this.zr.add(lsprite);
      lsprites.push(lsprite);
      lparams.push(lparam);

      // to top
      let tparam = {
        count: 0,
        posy: ystart,
        height: 1
      };
      let tsprite = new zrender.Rect({
        shape: {
          width: this.canvasWidth,
          height: tparam.height
        },
        style: {
          fill: new zrender.LinearGradient(
            0, 0, 0, 1,
            [
              {offset:0, color:'#FFF0'},
              {offset:0.2, color:'#FFF'},
              {offset:0.8, color:'#FFF'},
              {offset:1, color:'#FFF0'}
            ]
          ),
          opacity: 0.1
        },
        position: [0, tparam.posy],
        z: 1
      });
      this.zr.add(tsprite);
      tsprites.push(tsprite);
      tparams.push(tparam);

      // to bottom
      let bparam = {
        count: 0,
        posy: ystart,
        height: 1
      };
      let bsprite = new zrender.Rect({
        shape: {
          width: this.canvasWidth,
          height: bparam.height
        },
        style: {
          fill: new zrender.LinearGradient(
            0, 0, 0, 1,
            [
              {offset:0, color:'#FFF0'},
              {offset:0.2, color:'#FFF'},
              {offset:0.8, color:'#FFF'},
              {offset:1, color:'#FFF0'}
            ]
          ),
          opacity: 0.1
        },
        position: [0, bparam.posy],
        z: 1
      });
      this.zr.add(bsprite);
      bsprites.push(bsprite);
      bparams.push(bparam);
    }

    // TODO
    // this.p1text1.attr({position:[this.v1text1_x, this.v1text1_y]});

    this.params.bgMoverCount++;
  }
}

/**
 * @param {number} canvasWidth 
 * @param {number} canvasHeight 
 * @param {Color} color 
 */
function createBackground(canvasWidth, canvasHeight, color) {
  return new zrender.Rect({
    shape: {
      width: canvasWidth,
      height: canvasHeight
    },
    style: {
      fill: new zrender.LinearGradient(
        0, 0, 1, 0,
        [
          {offset:0, color:color.dark_bg[1]},
          {offset:0.333, color:color.dark_bg[0]},
          {offset:0.5, color:'white'},
          {offset:0.667, color:color.dark_bg[0]},
          {offset:1, color:color.dark_bg[1]}
        ]
      ),
      opacity: 1
    },
    position: [0, 0],
    z: 0
  })
}

/**
 * 扫描线
 * @param {number} canvasWidth
 * @param {number} canvasHeight  
 */
function createScanLine(canvasWidth, canvasHeight) {
  let lineList = [];
  for (let i = 0; i < canvasHeight / 3; i ++) {
    let line = new zrender.Line({
      shape: {
        x1: 0,
        y1: i * 3,
        x2: canvasWidth,
        y2: i * 3
      }
    });
    lineList.push(line);
  }
  return new zrender.path.mergePath(lineList, {
    style: {
      stroke: 'black',
      fill: 'none',
      opacity: 0.3,
      lineWidth: 1
    },
    position: [0, 0],
    z: 0
  });
}

/**
 * 背景白色纵线组
 * @param {number} canvasWidth
 * @param {number} canvasHeight  
 */
function createBgTiles(canvasWidth, canvasHeight) {
  let xoffset = 21;
  let xstart = canvasWidth / 2 - xoffset * 10;
  let array = [];
  for (let i = 0; i < 20; i++) {
    array.push(new zrender.Rect({
      shape: {
        width: xoffset,
        height: canvasHeight
      },
      style: {
        fill: 'white',
        opacity: (i > 10) ? 1 - (i - 10) * 0.1 : 0.1 * i + 0.1
      },
      position: [xstart + xoffset * i, 0],
      z: 1
    }));
  }
  return array;
}

/**
 * 中心白横线
 * @param {number} canvasWidth
 * @param {Layout} layout 
 */
function createBgHorizontal(canvasWidth, layout) {
  return new zrender.Rect({
    shape: {
      width: canvasWidth,
      height: 6
    },
    style: {
      fill: 'white',
      opacity: 0.25
    },
    position: [0, layout.bgMoverOriY - 3],
    z: 1
  })
}

/**
 * 屏幕上两个挖空的
 * @param {Layout} layout 
 */
function createScreenRemovers(layout) {
  return layout.screens.map((item, index) => {
    return new zrender.Rect({
      shape: {
        width: item.width,
        height: item.height
      },
      style: {
        fill: '#FFF',
        opacity: 1,
        blend: 'destination-out'
      },
      position: [item.x, item.y],
      z: 15
    });
  });
}

export default Transfer;